#pragma once
#ifndef __TSGMATH__
#define __TSGMATH__


#include "tsg.h"


namespace tsg
{
	/** Math helper functions. You should not add anything to this namespace. */
	namespace math
	{

		/** 2D vector addition. */
		Vector2  add          ( const Vector2&, const Vector2& );
		/** 2D dot product. */
		float    dotProduct   ( const Vector2&, const Vector2& );
		/** Magnitude of a 2D vector. */
		float    length       ( const Vector2& );
		/** Squared magnitude of a 2D vector. This is a more efficient measure of vector magnitude. */
		float    lengthSq     ( const Vector2& );
		/** 2D linear interpolation. @param s Should be in the range [0,1]. */
		Vector2  lerp         ( const Vector2&, const Vector2&, float s );
		/** Obtain a 2D unit vector. @param v Must not be a null vector. */
		Vector2  normalize    ( const Vector2& v );
		/** Scalar 2D vector multiplication. */
		Vector2  scale        ( const Vector2&, float );
		/** 2D vector subtraction. */
		Vector2  subtract     ( const Vector2&, const Vector2& );

		/** 3D vector addition. */
		Vector3  add          ( const Vector3&, const Vector3& );
		/** 3D cross product. */
		Vector3  crossProduct ( const Vector3&, const Vector3& );
		/** 3D dot product. */
		float    dotProduct   ( const Vector3&, const Vector3& );
		/** Magnitude of a 3D vector. */
		float    length       ( const Vector3& );
		/** Squared magnitude of a 3D vector. */
		float    lengthSq     ( const Vector3& );
		/** 3D linear interpolation. @param s Should be in the range [0,1]. */
		Vector3  lerp         ( const Vector3&, const Vector3&, float s );
		/** Obtain a 3D unit vector. @param v Must not be a null vector. */
		Vector3  normalize    ( const Vector3& v );
		/** Scalar 3D vector multiplication. */
		Vector3  scale        ( const Vector3&, float );
		/** 3D vector subtraction. */
		Vector3  subtract     ( const Vector3&, const Vector3& );

		/** Homogeneous divide. The w coordinate is left intact by the operation. */
		Vector3  standardize  ( const Vector4& );
		/** Left-hand side Vector/Matrix multiplication. This is generally for row vectors and matrices designed for them. */
		Vector4  transform    ( const Vector4&, const Matrix& );
		/** Right-hand side Matrix/Vector multiplication. This is generally for column vectors and matrices designed for them. */
		Vector4  transform    ( const Matrix&, const Vector4& );

		/** Euler rotation matrix.  The order is XYZ for column vectors. */
		Matrix   eulerRotate  ( float x, float y, float z );
		/** Frenet transformation matrix.  This aligns the local z-axis with direction and the local y-axis approximately with up. This is for column vectors. */
		Matrix   frenet       ( const Vector3& position, const Vector3& direction, const Vector3& up );
		/** The identity matrix. */
		Matrix   identity     ( );
		/** A view transformation matrix.  The camera is placed at the pos location facing interest location with the local y-axis approximately aligned with up. */
		Matrix   lookAt       ( const Vector3& pos, const Vector3& interest, const Vector3& up );
		/** Matrix multiplication. */
		Matrix   multiply     ( const Matrix&, const Matrix& );
		/** An orthographic projection matrix. Use this for drawing HUDs. */
		Matrix   orthographic ( float left, float right, float bottom, float top );
		/** A perspective projection matrix.  Use this for 3D scenes. @param fov Vertical field of view angle. @param aspect The aspect ratio of the output image. @param near Near plane clipping distance; this should be positive and less than far. @param far Far plane clipping distance; this should be positive and greater than near. */
		Matrix   perspective  ( float fov, float aspect, float near, float far );
		/** Rotation transformation. Rotation about an axis specified by xyz by angle degrees. */
		Matrix   rotate       ( float angle, float x, float y, float z );
		/** Rotation transform about X. Angle is in degrees. */
		Matrix   rotateX      ( float );
		/** Rotation transform about Y. Angle is in degrees. */
		Matrix   rotateY      ( float );
		/** Rotation transform about Z. Angle is in degrees. */
		Matrix   rotateZ      ( float );
		/** Scaling transformation. */
		Matrix   scale        ( float x, float y, float z );
		/** Translation transformation. */
		Matrix   translate    ( float x, float y, float z );
		/** Transpose a matrix. */
		Matrix   transpose    ( const Matrix& );

		/** Compute a cubic Bezier basis function.  @param t Should be in the range [0,1]. @param i Which basis function to compute. Should be in the range [0,3]. @param derivative Which derivative function to compute.  Should be in the range [0,2].  Use 0 for position, 1 for tangent, and 2 for curvature. */
		float    bezier3      ( float t, unsigned int i, unsigned int derivative );
		/** Compute a BSpline basis function using the Cox de Boor algorithm.  @param t Must be in the range of the knot vector. @param i Which basis function to compute. Must be in the range [0,nPoints-1]. @param degree The degree of parametric equation to apply. @param knotVector The vector of parameter values for the basis functions. The number of knot values must equal number of control points + the degree + 1. */
		float    coxDeBoor    ( float t, unsigned int i, unsigned int degree, const float* knotVector );

	};

};


#endif
